﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
using Microsoft.SharePoint.Utilities;
using System.Reflection;

namespace Mystery.SharePoint
{
	/// <summary>
	/// Extension methods for SPSite
	/// </summary>
	public static class SPSiteExtensions
	{		
		/// <summary>
		/// Rebases the URL to match the zone of the SPSite
		/// </summary>
		/// <param name="site"></param>
		/// <param name="url">URL to rebase</param>
		/// <returns>New URL</returns>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", 
			"CA1055:UriReturnValuesShouldNotBeStrings", 
			Justification="SharePoint has a lot of API's that use strings. There is an overload for those times that we need an Uri")]
		public static string RebaseUrl(this SPSite site, string url)
		{
			if (site == null) throw new ArgumentNullException("site");

			Uri uri = new Uri(url);
			return site.RebaseUrl(uri).ToString();
		}
		/// <summary>
		/// Rebases the URI to match the zone of the SPSite
		/// </summary>
		/// <param name="site"></param>
		/// <param name="uri">URI to rebase</param>
		/// <returns>New URI</returns>
		public static Uri RebaseUrl(this SPSite site, Uri uri)
		{
			if (site == null) throw new ArgumentNullException("site");

			return SPFarm.Local.AlternateUrlCollections.RebaseUriWithAlternateUri(uri, site.Zone);
		}
		
		/// <summary>
		/// Determines if this is the root site collection in the web application
		/// </summary>
		/// <param name="site"></param>
		/// <returns></returns>
		public static bool IsRoot(this SPSite site)
		{
			if (site == null) throw new ArgumentNullException("site");

			return (site.ServerRelativeUrl == "/");
		}
		/// <summary>
		/// Finds the root SPSite
		/// </summary>
		/// <param name="site"></param>
		/// <returns>A reference to the root SPSite. This has to be disposed of by the caller.</returns>
		public static SPSite FindRootSPSite(this SPSite site)
		{
			if (site == null) throw new ArgumentNullException("site");

			Uri uri = site.WebApplication.GetResponseUri(site.Zone);
			return new SPSite(uri.ToString());
		}
		/// <summary>
		/// Performs synchronization of site collection administrators
		/// </summary>
		/// <param name="site"></param>
		/// <param name="target">Target site collection</param>
		public static void SynchronizeAdmins(this SPSite site, SPSite target)
		{
            if (site == null) throw new ArgumentNullException("site");
            if (target == null) throw new ArgumentNullException("target");
            if (site.ID == target.ID) return; // no point synchronizing your own site
            
			Logger.L.AddInformation(Category.Administration,
						"Synchronizing admins from {0} to {1}", site.Url, target.Url);

			site.RootWeb.SiteUsers.Synchronize(target.RootWeb.SiteUsers, true);
		}
		/// <summary>
		/// Performs synchronization of the visitor group
		/// </summary>
		/// <param name="site"></param>
		/// <param name="target"></param>
		public static void SynchronizeVisitors(this SPSite site, SPSite target)
		{
            if (site == null) throw new ArgumentNullException("site");
            if (target == null) throw new ArgumentNullException("target");
            if (site.ID == target.ID) return; // no point synchronizing your own site

			if ((site.RootWeb.AssociatedVisitorGroup != null) &&
					(target.RootWeb.AssociatedVisitorGroup != null))
			{
				Logger.L.AddInformation(Category.Administration,
					"Synchronizing visitors from {0} to {1}", site.Url, target.Url);

				site.RootWeb.AssociatedVisitorGroup.Users.Synchronize(
					target.RootWeb.AssociatedVisitorGroup.Users, false);
			}
		}
        /// <summary>
        /// Syncrhonizes the search box properties from one site collection to another
        /// </summary>
        /// <param name="site">The source site</param>
        /// <param name="target"> the target site</param>
        public static void SynchronizeSearchBox(this SPSite site , SPSite target)
        {
            if (site == null) throw new ArgumentNullException("site");
            if (target == null) throw new ArgumentNullException("target");
            if (site.ID == target.ID) return; // no point synchronizing your own site

            bool updated = false;

            //!!!! The spelling mistake is not a mistake on my part, but the SharePoint team's
            foreach (var pn in new string[] { "SRCH_ENH_FTR_URL", "SRCH_SITE_DROPDOWN_MODE", "SRCH_TRAGET_RESULTS_PAGE"})
            {
                string v = site.RootWeb.AllProperties.Read(pn, "");
                if (string.IsNullOrEmpty(v) == false)
                {
                    updated |= target.RootWeb.AllProperties.Write(pn, v);
                }
            }
            if (updated == true)
            {
                target.RootWeb.Update();
            }
        }
	}
}
